package com.xyrl.project.common.csr.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xyrl.common.base.exception.XyrlException;
import com.xyrl.common.util.ObjectUtil;
import com.xyrl.common.util.RedisUtil;
import com.xyrl.common.util.StringUtil;
import com.xyrl.project.common.authentication.JWTUtil;
import com.xyrl.project.common.authentication.LoginInfo;
import com.xyrl.project.common.common.service.AttachmentService;
import com.xyrl.project.common.common.vo.AttachmentVo;
import com.xyrl.project.common.constant.XyrlConstant;
import com.xyrl.project.common.csr.dao.CsrUserMapper;
import com.xyrl.project.common.csr.entity.CsrUser;
import com.xyrl.project.common.csr.enu.CsrUserType;
import com.xyrl.project.common.csr.service.CsrUserService;
import com.xyrl.project.common.csr.vo.CsrUserVo;
import com.xyrl.project.common.store.dao.StoreMapper;
import com.xyrl.project.common.store.entity.Store;
import com.xyrl.project.common.store.entity.StoreLegal;
import com.xyrl.project.common.store.enu.StoreStatus;
import com.xyrl.project.common.store.service.StoreLegalService;
import com.xyrl.project.common.util.MD5Util;
import com.xyrl.project.common.util.XyrlUtil;
import com.xyrl.starter.lock.redis.lock.DistributedLock;
import com.xyrl.third.baidu.service.PersonVerifyService;
import com.xyrl.third.baidu.vo.BaiduPersonVerifyVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.Date;
import java.util.List;


/**
 * @author 徐恩源
 * @version 1.0
 * @className CustomerUserServiceImpl.java
 * @company 重庆星纭融链科技公司
 * @date 2019-12-27 11:25:42
 * @Description 商户serviceImpl
 */
@Service
@Slf4j
public class CsrUserServiceImpl extends ServiceImpl<CsrUserMapper, CsrUser> implements CsrUserService {
    @Autowired
    private ObjectMapper mapper;
    @Autowired
    private DistributedLock distributedLock;
    @Autowired
    private StoreLegalService storeLegalService;
    @Autowired
    private AttachmentService attachmentService;
    @Autowired
    private PersonVerifyService personVerifyService;

    @Autowired
    private StoreMapper storeMapper;

    /**
     * 根据登录用户取得用户信息
     *
     * @param userName 登录帐号
     * @author zhongp
     * @date 2019-12-30 13:44:15
     */
    @Override
    public CsrUser findByName(String userName) {
        CsrUser csrUser = baseMapper.selectOne(new LambdaQueryWrapper<CsrUser>().eq(CsrUser::getMobile, userName));
        try {
            RedisUtil.setData(XyrlConstant.CUSTOMER_USER_CACHE_PREFIX + userName, mapper.writeValueAsString(csrUser));
        } catch (Exception e) {
            log.error("缓存客户异常", e);
        }
        return csrUser;
    }

    @Override
    public CsrUser getByMobile(String mobile) {
        return super.getOne(new LambdaQueryWrapper<CsrUser>().eq(CsrUser::getMobile, mobile));
    }

    @Override
    public CsrUserVo loginByCsr(String mobile) throws XyrlException {
        CsrUser user = getByMobile(mobile);
        CsrUserVo userVo = new CsrUserVo();
        //判断用户是否为空
        if (ObjectUtil.isEmpty(user)) {
            String createLockKey = StringUtil.concat(XyrlConstant.LOCK_CREATE_CUSTOMER_USER_SIGN_KEY, mobile);
            boolean isLock = distributedLock.lockWithoutWaiting(createLockKey);
            try {
                if (isLock) {
                    //生成客户
                    user = new CsrUser();
                    user.setMobile(mobile);
                    user.setCreateTime(new Date());
                    user.setUserType(CsrUserType.admin);
                    user.setSalt(RandomStringUtils.randomAlphanumeric(20));
                    user.setVersion(0);
                    user.setLastTime(new Date());
                    this.baseMapper.insert(user);
                } else {
                    throw new XyrlException("正在执行，请稍后再试");
                }
            } finally {
                distributedLock.releaseLock(createLockKey);
            }
        } else {
            user.setLastTime(new Date());
            updateUserLoginTime(user.getId());
        }
        //生成token
        LoginInfo info = new LoginInfo(mobile, XyrlConstant.USER_TYPE_CUSTOMER);
        String token = XyrlUtil.encryptToken(JWTUtil.sign(info, mobile));
        BeanUtils.copyProperties(user, userVo);
        if(ObjectUtil.isNotEmpty(userVo.getTradePwd())){
            userVo.setSetTradePwd(true);
        }else{
            userVo.setSetTradePwd(false);
        }

        userVo.setToken(token);
        return userVo;
    }

    /**
     * 修改用户登录时间
     *
     * @param id
     */
    private void updateUserLoginTime(Long id) {
        UpdateWrapper<CsrUser> update = new UpdateWrapper<>();
        update.set("last_time", new Date());
        update.eq("id", id);
        baseMapper.update(new CsrUser(), update);
    }

    @Override
    public void setTradePwd(Long storeId,Long csrId, String pwd) throws XyrlException {
        if(!isPersonVerify(storeId)){
            throw new XyrlException("未进行实名认证");
        }
        CsrUser csrUser = this.baseMapper.selectById(csrId);
        if (ObjectUtil.isEmpty(csrUser)) {
            throw new XyrlException("当前用户不存在");
        }
        if (ObjectUtil.isNotEmpty(csrUser.getTradePwd())) {
            throw new XyrlException("己设置过交易密码");
        }
        //修改用户交易密码
        setTradePwd(csrId, csrUser.getSalt(), pwd);
    }

    @Override
    public void checkTradePwd(Long storeId, Long csrId, String pwd) throws XyrlException {
        if(!isPersonVerify(storeId)){
            throw new XyrlException("未进行实名认证");
        }
        CsrUser csrUser = this.baseMapper.selectById(csrId);
        if (ObjectUtil.isEmpty(csrUser)) {
            throw new XyrlException("当前用户不存在");
        }
        if (ObjectUtil.isEmpty(csrUser.getTradePwd())) {
            throw new XyrlException("未设置交易密码");
        }
        String oldTradePwd = MD5Util.encrypt(csrUser.getSalt(), pwd);
        if (!csrUser.getTradePwd().equalsIgnoreCase(oldTradePwd)) {
            throw new XyrlException("交易密码错误");
        }
    }

    @Override
    public String personVerify(Long storeId, Long[] attIds) throws XyrlException {
        // 保存身份证信息
        StoreLegal storeLegal = this.findStoreLegalByCsrId(storeId);
        if (ObjectUtil.isEmpty(storeLegal)) {
            return "未进行实名认证";
        }
        List<AttachmentVo> attVoList = attachmentService.findListByIdList(Arrays.asList(attIds));
        if (attVoList.size() != attIds.length) {
            return "认证失败，未找到认证图片";
        }
        log.debug("开始调用实名认证,认证头像:{}", attVoList.get(0).getShowUrl());
        //身份认证(调用百度身份认证 与公安中的身份证照片进行核对）
        BaiduPersonVerifyVo verifyInfo = personVerifyService.urlPersonVerify(attVoList.get(0).getShowUrl(), storeLegal.getRealName(), storeLegal.getIdCard());
        //根据比对分值进行判断身份认证是否成功
        if (ObjectUtil.isEmpty(verifyInfo.getResult()) || ObjectUtil.isEmpty(verifyInfo.getResult().getScore())
                || verifyInfo.getResult().getScore().doubleValue() < 80) {
            return "实时认证未通过";
        }
        RedisUtil.setMap(XyrlConstant.FIND_TRADE_PWD_CACHE_KEY, verifyInfo.getLogId(), verifyInfo.getLogId());
        return verifyInfo.getLogId();
    }

    /**
     * 修改用户交易密码
     *
     * @param csrId
     * @param salt
     * @param pwd
     * @author zhongp
     * @date 2020-01-08 16:38:27
     */
    private void setTradePwd(Long csrId, String salt, String pwd) {
        CsrUser csrUser = new CsrUser();
        csrUser.setId(csrId);
        if (ObjectUtil.isEmpty(salt)) {
            salt = RandomUtil.randomString(20);
            csrUser.setSalt(salt);
        }
        String tradePwd = MD5Util.encrypt(salt, pwd);
        csrUser.setTradePwd(tradePwd);
        this.baseMapper.updateById(csrUser);
    }

    @Override
    public void updateTradePwd(Long storeId,Long csrId, String oldPwd, String newPwd) throws XyrlException {
        if(!isPersonVerify(storeId)){
            throw new XyrlException("未进行实名认证");
        }
        CsrUser csrUser = this.baseMapper.selectById(csrId);
        if (ObjectUtil.isEmpty(csrUser)) {
            throw new XyrlException("当前用户不存在");
        }
        if (ObjectUtil.isEmpty(csrUser.getTradePwd())) {
            throw new XyrlException("未设置交易密码");
        }
        String oldTradePwd = MD5Util.encrypt(csrUser.getSalt(), oldPwd);
        if (!csrUser.getTradePwd().equalsIgnoreCase(oldTradePwd)) {
            throw new XyrlException("原始密码不一至");
        }
        //修改用户交易密码
        setTradePwd(csrId, csrUser.getSalt(), newPwd);
    }

    @Override
    public void findTradePwd(Long storeId,Long csrId, String pwd, String verifyId) throws XyrlException {
        if(!isPersonVerify(storeId)){
            throw new XyrlException("未进行实名认证");
        }
        Object cacheVerifyId = RedisUtil.getMap(XyrlConstant.FIND_TRADE_PWD_CACHE_KEY, verifyId);
        if (ObjectUtil.isEmpty(cacheVerifyId)) {
            throw new XyrlException("身份认证未通过");
        }
        if (!cacheVerifyId.toString().equalsIgnoreCase(verifyId)) {
            throw new XyrlException("身份认证未通过");
        }
        CsrUser csrUser = this.baseMapper.selectById(csrId);
        if (ObjectUtil.isEmpty(csrUser)) {
            throw new XyrlException("当前用户不存在");
        }
        //修改用户交易密码
        setTradePwd(csrId, csrUser.getSalt(), pwd);

        RedisUtil.delMap(XyrlConstant.FIND_TRADE_PWD_CACHE_KEY, verifyId);
    }

    private StoreLegal findStoreLegalByCsrId(long storeId) {
        LambdaQueryWrapper<StoreLegal> wrapper = new LambdaQueryWrapper();
        wrapper.eq(StoreLegal::getStoreId, storeId);
        wrapper.eq(StoreLegal::getEnableFlag, XyrlConstant.YES);
        return storeLegalService.getOne(wrapper);
    }

    /**
     * 校验商户是否进行实名认证
     *
     * @param storeId
     * @author zhongp
     * @date 2020-01-08 17:36:25
     */
    private boolean isPersonVerify(Long storeId) {
        Store store = storeMapper.selectById(storeId);
        if (ObjectUtil.isEmpty(store)) {
            return false;
        }
        //商户状态处于创建  跟踪 时未通过实名认证
        if (!store.getStatus().equals(StoreStatus.create.getValue()) && !store.getStatus().equals(StoreStatus.follow.getValue())) {
            return true;
        }
        return false;
    }
}
